home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ddj0492.zip / CTIME2.ASC < prev    next >
Text File  |  1992-02-04  |  8KB  |  206 lines

  1. /*  Elik Listing 1: datetime.h
  2.  
  3. Header file for ctime2.c
  4.  
  5. */
  6.  
  7. #ifndef DATE_TIME_H #define DATE_TIME_H
  8.  
  9. #define SECS_PER_MIN    60
  10. #define SECS_PER_HOUR    (SECS_PER_MIN*60)
  11. #define SECS_PER_DAY    (SECS_PER_HOUR*24L)   /* long constant! */
  12. #define HOURS_PER_DAY    24
  13. #define DAYS_PER_WEEK    7
  14. #define DAYS_PER_YEAR    365
  15. #define LEAP_PERIOD    (365*4+1)
  16.  
  17. #define BASE_YEAR    1970
  18. #define UNTIL_1980    (365*10+2)            /* 01-01-1970 to 01-01-1980 */
  19. #define UNTIL_FEB29    (365*2+31+29-1)       /* 01-01-1970 to 29-02-1972 */
  20. #define UNTIL_2000    (365*30+7+31+28-1)    /* 01-01-1970 to 28-02-2000 */
  21. è#define THURSDAY    4
  22. #define APRIL    (90-1)
  23. #define OCTOBER    (273-1)
  24.  
  25. /*
  26. Similar structure (struct tm) is defined in <time.h>, but I prefer to use my own - I think it makes code clearer. (And, also, my structure is slightly shorter).
  27. */ struct date_time {
  28. short    yr,    /* year */
  29.     mo,    /* month (0-11) */
  30.     dy,    /* day */
  31.     dw,    /* day of week (0-6) */
  32.     hr,    /* hours */
  33.     mn,    /* minutes */
  34.     sc;    /* seconds */
  35. };
  36.  
  37. typedef int boolean; typedef unsigned short word; typedef unsigned long dword;
  38.  
  39. char *ctime2 (const time_t *time); time_t dt2time (struct date_time *dtp);
  40.  
  41. #endif
  42.  
  43.  
  44. /* Elik Listing 2: ctime2.c
  45.  
  46. CorrecteΣ versioε oµ ctime▓ b∙ U.ELI╦ ¿ DD╩ #17╖ Junσ 1991¼ ì
  47. 'Usinτ thσ Rea∞-Timσ Clockº b∙ KennetΦ Roach¼ p.26¼ listing≤ oε ì
  48. p.88⌐ )
  49.  
  50. */
  51.  
  52. #include <stdio.h> #include <time.h> #include "datetime.h"
  53.  
  54. static word nearest_sunday (word days_yr, word year);
  55.  
  56. /*
  57. Replacement to C library ctime() function. Working more than 300% (QuickC 2.01) faster than ctime().
  58. */ char *ctime2 (const time_t *tptr) {
  59.  
  60. static char time_str[26] = "www mmm dd HH:MM:SS yyyy\n"; static char *months[12] = {
  61. "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  62. }, *wdays[7] = {
  63. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static unsigned short month_days[] = {
  64. 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
  65.  
  66. struct date_time dt;    /* we must fill this structure
  67. and then convert it to string */ dword time; word days; register char *chptr; register word i;
  68.  
  69. time = *tptr - timezone; /* because C time() function returns GMT value */ days = (word)(time / SECS_PER_DAY); /* days since 1970 */
  70.  
  71. if (days < UNTIL_1980)
  72. return NULL;         /* on dates before 1980, ctime() returns NULL */
  73.  
  74. /* first, calculating time - it's simple */ time %= SECS_PER_DAY; /* seconds this day */ dt.hr = (word)(time / SECS_PER_HOUR); i = (word)(time % SECS_PER_HOUR); /* seconds this hour */ dt.mn = i / SECS_PER_MIN; dt.sc = i % SECS_PER_MIN;
  75. è/* day of week - it's simple too */ dt.dw = (days + THURSDAY) % DAYS_PER_WEEK;
  76.  
  77. /* then calculating date - it's little bit more complex */ i = days - UNTIL_FEB29; /* days since Feb 29 1972 */ days -= (i / LEAP_PERIOD + 1); /* delete all Feb 29s */ /* now we can calculate everything as if leap years doesn't exist */
  78.  
  79. dt.yr = days / DAYS_PER_YEAR + BASE_YEAR; if ((i % LEAP_PERIOD) == 0) { /* today Feb 29th special case */
  80. dt.mo = 1; /* Feb */ dt.dy = 29;
  81. } else {
  82. days %= DAYS_PER_YEAR; /* days this year */ if (
  83. daylight /* if a daylight-saving-time zone is specified */
  84.  
  85. && days >= nearest_sunday (
  86. dt.yr>1986 ? APRIL+1 : APRIL+24, dt.yr) && days < nearest_sunday (OCTOBER+25, dt.yr) /* and this day belongs to summer period */ /* (1980-1986: Apr 24 - Oct 25 */ /* after 1986: Apr 1 - Oct 25) */
  87. ) {
  88. /* then it's one hour later */ if (++dt.hr == HOURS_PER_DAY) {
  89. days++; dt.dw = (dt.dw+1) % DAYS_PER_WEEK; dt.hr = 0;
  90. } } for (i=1; month_days[i] <= days; i++)
  91. ; dt.mo = --i; /* months must be 0 - 11 */ dt.dy = days - month_days[i] + 1;
  92. }
  93.  
  94. /* now fill the string */
  95.  
  96. /* To use sprintf() is the simpliest way (for programmer, of course),
  97. but it's executing VERY slowly, especially in QuickC and MSC. Code below may look cumbersome, but it's MUCH quicker.
  98.  
  99. sprintf (time_str, "%3s %3s %02d %02d:%02d:%02d %04d\n",
  100. wdays[dt.dw], months[dt.mo], dt.dy, dt.hr, dt.mn, dt.sc, dt.yr); */
  101.  
  102. chptr = wdays[dt.dw]; time_str[0] = chptr[0]; time_str[1] = chptr[1]; time_str[2] = chptr[2];
  103.  
  104. chptr = months[dt.mo]; time_str[4] = chptr[0]; time_str[5] = chptr[1]; time_str[6] = chptr[2];
  105.  
  106. time_str[8] = (char)(dt.dy / 10 + '0'); time_str[9] = (char)(dt.dy % 10 + '0');
  107.  
  108. time_str[11] = (char)(dt.hr / 10 + '0'); time_str[12] = (char)(dt.hr % 10 + '0');
  109.  
  110. time_str[14] = (char)(dt.mn / 10 + '0'); time_str[15] = (char)(dt.mn % 10 + '0');
  111.  
  112. time_str[17] = (char)(dt.sc / 10 + '0'); time_str[18] = (char)(dt.sc % 10 + '0');
  113.  
  114. time_str[20] = (char)(dt.yr / 1000 + '0');    i = dt.yr % 1000;
  115. time_str[21] = (char)(i / 100 + '0');    i %= 100;
  116. time_str[22] = (char)(i / 10 + '0'); time_str[23] = (char)(i % 10 + '0');
  117.  
  118. return time_str; }
  119.  
  120. /*
  121. Returns nearest Sunday after (and including) given date. <days_yr> must be AFTER February!
  122. */ static word nearest_sunday (word days_yr, word year) { word dwk, /* day of week (0 - 6) */
  123. yr=year-1970;   /* years since 1970 */
  124.  
  125. dwk = ((days_yr + yr * DAYS_PER_YEAR + (yr+2) / 4)     /* days since 1970 */
  126. - 1 + THURSDAY) % DAYS_PER_WEEK; return days_yr + ((DAYS_PER_WEEK-1)-dwk);
  127. }
  128.  
  129. /* Elik Listing 3: compiler.hè
  130. Macros to determine used compiler.
  131.  
  132. */
  133.  
  134. #ifdef _QC
  135. #define COMPILER "QuickC" #else
  136. #ifdef _MSC_VER
  137. #define COMPILER "MSC" #else
  138. #ifdef __BORLANDC__
  139. #define COMPILER "BorlandC++" #else
  140. #ifdef __TURBOC__
  141. #define COMPILER "TurboC" #else
  142. #define COMPILER "Unknown compiler" #endif
  143. #endif #endif
  144. #endif
  145.  
  146. /* Elik Listing 4: cmpctim1.c
  147.  
  148. Test no.1 for ctime2() function by U.ELIK
  149.  
  150. */
  151.  
  152. #include <stdio.h> #include <time.h> #include "datetime.h" #include "compiler.h"
  153.  
  154. #define TEST_TICKS (5*18+1)
  155.  
  156. static unsigned long far *tickptr = (unsigned long far *)0x0000046C;
  157.  
  158. unsigned long test (char * (*fun) (const time_t * )) { unsigned long count=0, start; time_t t;
  159.  
  160. time (&t); start = *tickptr; while (*tickptr == start); for (start+=(TEST_TICKS+1); *tickptr < start; t++) {
  161. (*fun) (&t); count++;
  162. } return count;
  163. }
  164.  
  165. unsigned long percent (unsigned long c1, unsigned long c2) { unsigned long ret;
  166.  
  167. c1 *= 100; ret = c1 / c2; if (c1 % c2 >= 50)
  168. ret++; return ret;
  169. }
  170.  
  171. void main (int argc, char *argv[]) { unsigned long n1, n2;
  172.  
  173. printf ("\nTesting %s code...\n", COMPILER); printf ("ctime2() called %ld times\n", n2=test (ctime2)); printf ("ctime() called %ld times\n", n1=test (ctime)); if (n1>n2)
  174. printf ("ctime() %ld%% faster than ctime2()\n", percent (n1, n2)); else
  175. printf ("ctime2() %ld%% faster than ctime()\n", percent (n2, n1)); }
  176.  
  177. /* Elik Listing 5: cmpctim2.c
  178.  
  179. Test no.2 for ctime2() function by U.ELIK
  180.  
  181. */
  182.  
  183. #include <stdio.h> #include <time.h> #include "datetime.h" #include "compiler.h"è
  184. #define TEST_TICKS (5*18+1)
  185.  
  186. static unsigned long far *tickptr = (unsigned long far *)0x0000046C;
  187.  
  188. unsigned test (char * (*fun) (const time_t * )) { unsigned count=0; unsigned long start; time_t t;
  189.  
  190. time (&t); start = *tickptr; while (*tickptr == start); for (start+=(TEST_TICKS+1); *tickptr < start; ) {
  191. (*fun) (&t); count++;
  192. } return count;
  193. }
  194.  
  195. unsigned percent (unsigned long c1, unsigned long c2) { unsigned ret;
  196.  
  197. c1 *= 100; ret = (unsigned)(c1 / c2); if (c1 % c2 >= 50)
  198. ret++; return ret;
  199. }
  200.  
  201. void main (int argc, char *argv[]) { unsigned n1, n2;
  202.  
  203. printf ("\nTesting %s code...\n", COMPILER); printf ("ctime2() called %u times\n", n2=test (ctime2)); printf ("ctime() called %u times\n", n1=test (ctime)); if (n1>n2)
  204. printf ("ctime() %u%% faster than ctime2()\n", percent (n1, n2)); else
  205. printf ("ctime2() %u%% faster than ctime()\n", percent (n2, n1)); }
  206.